var Poker = require('../Poker/Poker');
var PokerRoom = require('../Poker/room').PokerRoom;

var Const = require('./const');
var SubCode = require('../subCode');

var RoundStatus = {
    'WAITING': 1,   // 等待其它玩家准备
    'PREPARE': 2,   // 准备人数足够，将继续等待，其它玩家依然可以准备
    'READY': 3,     // 就绪，开始游戏
    'ROBDEALER' : 4,// 抢庄
    'ADDANTE': 5,   // 加注
    'PLAY': 6       // 玩家选牌
};

exports.JCNNRoom = PokerRoom.extend({
    _roundStatus: RoundStatus.WAITING,

    _dealerIndex: 0,           // 庄家坐位
    _selectWaitTime: 0,        // 开始选牌的时间
    _waitRobTime: 0,           // 开始抢庄的时间
    _waitAddAnteTime: 0,       // 开始加注的时间
    _waitTimer: 0,             // 计时器
    _roundAnte: 0,             // 本轮注数
    _roundWinPlayer: 0,        // 本轮赢家
    _roundDateStamp: 0,        // 当前局数操作的时间戳
    _roundTurn: 0,
    _baseAnte: 0,              // 基础下注

    init: function(rid, creator, msg) {
        this._super(rid, creator, msg);

        this._roundStatus = RoundStatus.WAITING;

        // 房主当庄和轮流当庄，默认第一局都是房主当庄
        if (this.getOption("qZhuangMode") == Const.qZhuangMode.GDQZ) {
            this._dealerIndex = 1;
        }

        this._waitTimer = 0;
        this._selectWaitTime = 0;
        this._roundAnte = 0;
        this._roundTurn = 0;
        this._roundDateStamp = 0;
        this._baseAnte = 0;
    },

    /**
     * 获取当前步骤的等待时间
     * @returns {*}
     */
    getWaitStepTime : function () {

        var step = this._roundStatus;
        var time;
        switch (step) {
            case RoundStatus.ADDANTE:time = this.getHideOption("addAnteWaitMS");break;
            case RoundStatus.PLAY: time = this.getHideOption("playWaitMS");break;
            case RoundStatus.ROBDEALER:time = this.getHideOption("robDealerWaitMS");break;
        }

        return time;
    },

    /******************************************************************
     * 重载的接口
     ******************************************************************/

    getRoundInfo: function() {
        var info = this._super();
        info.robDealerWaitMS = this.getHideOption("robDealerWaitMS");
        info.selectWaitMS = this.getHideOption("selectWaitMS");
        info.dealerIndex = this.getDealerIndex();
        return info;
    },

    getReconnectInfo: function (rePlayer) {
        var info = this._super(rePlayer);
        info.dealer = this._dealerIndex;
        info.selectWaitTime = this._selectWaitTime;
        info.roundAnte = this._roundAnte;
        info.roundTurn = this._roundTurn;
        info.roundStatus = this._roundStatus;

        var waitTime = this.getWaitStepTime();
        if (waitTime) {
            info.waitTime = waitTime;
            info.dateStamp = this._roundDateStamp;
        }

        return info;
    },

    getRoomConfig: function (){
        var cfg = this._super();
        cfg.destroyWaitTime = 60;
        cfg.waitTimeoutTime = 90;
        cfg.resetDestroyOnNewRound = 0;
        cfg.enableJoinAfterStart = this.getOption("joinAfterStart");
        return cfg;
    },

    /**
     * 检查是否可开始新的一局
     * @returns {boolean}
     */
    checkStartNewRound: function () {

        if (this.isPlaying()) {
            return false;
        }

        if (this.getReadyPlayerCount() == this.getPlayerCount()
        &&  this.getReadyPlayerCount() >= this.getSubConfig().minPlayer) {
            this._roundStatus = RoundStatus.READY;
            return true;
        }

        return false;
    },

    onPlayerQuitRoom: function(player) {
        this._super(player);

        if (this._roundStatus != RoundStatus.PREPARE) {
            return;
        }

        if (this.getReadyPlayerCount() <= this.getSubConfig().roomPlayerMin) {
            this.broadcast("onCancelStartWait", {});
            this._roundStatus = RoundStatus.WAITING;
        }
    },

    onBeforeStartNewRound: function() {
        this._super();
        this._selectWaitTime = 0;
        this._roundTurn = 0;

        // 如果是轮流坐庄的话, 需要这个时候进行庄家的移动
        if (this.getOption("qZhuangMode") == Const.qZhuangMode.GDQZ) {
            this._dealerIndex = 1;
        } else {
            // 需要抢庄的之前的庄位置重置
            this._dealerIndex = 0;
        }
    },

    onAfterStartNewRound: function() {
        this._super();
        this._startPlay();
    },

    // 主要用于中途解散没有销毁
    onDestroy: function() {
        this._super();
        if(this._waitTimer){
            clearTimeout(this._waitTimer);
        }

        // 清空默认配置
        this.getSubConfig().specCards = [];
    },

    onPlayerEnter: function (player) {

        if (player.getIndex() == 1 && this.getCurRound() == 0) {
            player.setInitScore (this.getOption ("shangZhuangScore"));
        }
    },

    onSettlement: function() {
        this._super();
        if(this.getOption("qZhuangMode") == Const.qZhuangMode.TBNN){

            var maxPlayer = null;
            var failArr = [];

            this.enumPlaying (function (eIndex, ePlayer) {
                if (ePlayer) {
                    ePlayer.checkPattern();
                    if (maxPlayer && maxPlayer.getIndex() != ePlayer.getIndex()) {
                        if (ePlayer.compareEach (maxPlayer)) {
                            failArr.push (maxPlayer);
                            maxPlayer = ePlayer;
                        }else {
                            failArr.push (ePlayer);
                        }
                    }else if (!maxPlayer) {
                        maxPlayer = ePlayer;
                    }
                }
            }.bind (this));

            // 获取加分倍数
            failArr.forEach (function (failer) {
                this.getAddScore (failer, maxPlayer);
            }, this);
            
        } else {
            // 首先结算房主的牌型
            // 然后让房主与玩家逐个比较
            var dealerPlayer = this.getDealerPlayer();
            if (!dealerPlayer.getSelectedCards()) {
                dealerPlayer.checkPattern();
            }
            this.enumPlaying(function(eIndex, ePlayer) {
                if (ePlayer && this.getDealerIndex() != eIndex) {
                    if (!ePlayer.getSelectedCards()) {
                        ePlayer.checkPattern();
                    }

                    this.compareEach (ePlayer, dealerPlayer);
                }
            }.bind (this));
        }

        // 根据当前的玩家积分判断玩家是否胜利
        this.enumPlaying (function (eIndex, ePlayer) {
            
            if (ePlayer) {
                if (ePlayer.getRoundScore() <= 0) {
                    ePlayer.addRoundInfoNum (-1);
                }else {
                    ePlayer.addRoundInfoNum (1);
                }
            }
        });
    },

    onCurRoundFinished: function() {
        this._super();
        this._roundStatus = RoundStatus.WAITING;
        this._roundDateStamp = 0;
        this._dealerIndex = 0;

        if(this._waitTimer){
            clearTimeout(this._waitTimer);
        }
    },

    /******************************************************************
     * 功能接口
     ******************************************************************/

    /**
     * 发送礼物
     * @param player
     * @param msg
     * @param callback
     */
    handleSendGift: function (player, msg, callback) {
        if (isNaN(msg.targetIndex)) {
            callback({code: Code.ARGS_INVALID});
            return;
        }

        var gameConfig = this.getGameConfig();
        var giftType = msg.type;
        var giftConfig = gameConfig.Gift[giftType];
        if (!giftConfig) {
            callback({code: Code.ARGS_VALUE_WRONG});
            return;
        }

        var targetIndex = parseInt(msg.targetIndex);
        var targetPlayer = this.getPlayerByIndex(targetIndex);
        if (!targetPlayer) {
            callback({code: Code.INDEX_INVALID});
            return;
        }

        if (!player.checkResource(giftConfig.costs)) {
            callback({code: Code.LACK_OF_COIN});
            return;
        }

        this.broadcast("onPlayerGift", {
            playerIndex: player.getIndex(),
            targetIndex: targetIndex,
            type: giftType
        });
        callback({});

        player.costResourceSync(giftConfig.costs);
    },

    handleRobDealer: function(player, msg, callback) {
        if (!this.isPlaying()) {
            callback({code: Code.ROOM_NOT_PLAYING}); return;
        }

        if (this.getOption("qZhuangMode") != Const.qZhuangMode.ZYQZ
            && this.getOption("qZhuangMode") != Const.qZhuangMode.MPQZ) {
            callback({code: SubCode.QZNN_MS_UNMATCH}); return;
        }

        if (player.getRobDealer() != -1) {
            callback({code: SubCode.QZNN_ROB_DEALER_SET}); return;
        }

        if (!msg.hasOwnProperty('value') || isNaN(msg.value)) {
            callback({code: Code.ARGS_INVALID}); return;
        }

        var value = parseInt(msg.value);
        if (value < 0 || value > 4) {
            callback({code: Code.ARGS_VALUE_WRONG}); return;
        }

        player.setRotDealer(value);
        this.broadcast("onPlayerRobDealer", {
            playerIndex: player.getIndex(),
            value: value
        });
        callback({});

        var isAllSet = true;
        this.enumPlaying(function(eIndex, ePlayer) {
            if (ePlayer.getRobDealer() == -1) {
                isAllSet = false;
            }
        });

        if (isAllSet) {
            if (this._waitTimer) {
                clearTimeout(this._waitTimer);
            }

            this._dealRobDealerAllSet();
        }
    },

    handlePlayCards : function (player, msg, callback) {

        if (!player.isPlaying()) {
            callback({code: Code.PLAYER_NOT_PLAYING}); return;
        }
        if (!this.isPlaying()) {
            callback({code: Code.ROOM_NOT_PLAYING}); return;
        }
        if (this.isCurRoundFinished()) {
            callback({code: Code.ROOM_ROUND_FINISHED}); return;
        }
        if(player._playCards){
            callback({code: SubCode.QZNN_PLAY_CARD_END}); return;
        }

        callback({});

        player._playCards = true;
        player.checkPattern();

        var resp = {
            playerIndex: player.getIndex(),
            handCards: player.getHandCards().getInitCards(),
            selectedCards: player.getSelectedCards(),
            niu: player.getRoundPattern(),
            niuScore: player.getRoundPatternScore()
        };
        this.broadcast("onPlayCards", resp);

        var isAllPlayed = true;
        this.enumPlaying(function(eIndex, ePlayer) {
            if (ePlayer._playCards == false) {
                isAllPlayed = false;
            }
        });

        if (isAllPlayed) {
            this.broadcast("onPlayCardsFinish", {});

            if (this._waitTimer) {
                clearTimeout(this._waitTimer);
            }

            this.settlementCurRound(500);
        }
    },

    //加注
    handleAddAnte : function (player, msg, callback) {
        if (!player.isPlaying()) {
            callback({code: Code.PLAYER_NOT_PLAYING}); return;
        }

        if (!this.isPlaying()) {
            callback({code: Code.ROOM_NOT_PLAYING}); return;
        }

        if (this.isCurRoundFinished()) {
            callback({code: Code.ROOM_ROUND_FINISHED}); return;
        }

        if (!msg.hasOwnProperty('num') || isNaN(msg.num)) {
            callback({code: Code.ARGS_INVALID}); return;
        }

        if(player.getAnte()){
            callback({code: SubCode.QZNN_ANTE_ADDED}); return;
        }

        var addAnet = msg.num;
        callback({});

        player.setAnte(addAnet);

        this.broadcast("onPlayerAddAnte", {
            playerIndex: player.getIndex(),
            num: addAnet
        });

        var isAllAdded = true;
        var room = this;
        this.enumPlaying(function(eIndex, ePlayer) {
            if (ePlayer.getAnte() == 0 && eIndex != room._dealerIndex) {
                isAllAdded = false;
            }
        });

        if (isAllAdded) {
            this.broadcast("onAddAnteFinish", {});

            if (this._waitTimer) {
                clearTimeout(this._waitTimer);
            }

            this._waitPlayCards();
        }
    },

    _startPlay: function() {
        if (this.getOption("qZhuangMode") == Const.qZhuangMode.GDQZ) {
            this._waitAddAnte();
        }else if(this.getOption("qZhuangMode") == Const.qZhuangMode.ZYQZ) {
            this._waitRobDealer();
        }else if (this.getOption("qZhuangMode") == Const.qZhuangMode.MPQZ) {
            this.initPlayersHandCards();
            this._waitRobDealer();
        }else if (this.getOption("qZhuangMode") == Const.qZhuangMode.TBNN) {
            // 通比模式..默认下注
            this._sendAllTuiZu();
            this._waitPlayCards();
        }
    },

    /**
     * 重载单独处理发送
     */
    initPlayersHandCards : function () {

        this.enumPlayers(function (eIndex, ePlayer) {

            if (ePlayer) {
                ePlayer.InitHandCards(this._publicCards.getCards(ePlayer.getInitHandCardNeedNum(), ePlayer.getInitHandCardPreCards()));
            }
        }.bind(this));
    },

    _waitRobDealer: function() {
        this._waitRobTime = Date.getStamp();
        this._roundDateStamp = new Date().getTime();

        this.broadcast("onStartRobDealer", {
            waitRobTime: this.getHideOption("robDealerWaitMS"),
            dateStamp: this._roundDateStamp
        });

        this._roundStatus = RoundStatus.ROBDEALER;

        if(this._waitTimer){
            clearTimeout(this._waitTimer);
        }

        this._waitTimer = setTimeout(function() {
            if (!this.isPlaying()) {
                return;
            }

            if (this._roundStatus != RoundStatus.ROBDEALER) {
                return;
            }

            this.enumPlaying(function(eIndex, ePlayer) {
                if (ePlayer.getRobDealer() == -1) {
                    ePlayer.setRotDealer(0);
                    this.broadcast("onPlayerRobDealer", {
                        playerIndex: ePlayer.getIndex(),
                        value: 0
                    });
                }
            }.bind(this));

            this._dealRobDealerAllSet();

        }.bind(this), this.getHideOption("robDealerWaitMS"));
    },

    _dealRobDealerAllSet: function() {

        var scoreRank = [];
        var noScoreRank = [];

        // 根据分数获取阶段
        this.enumPlayers(function (eIndex, ePlayer) {
            var point = ePlayer.getRobDealer();

            if (point > 0) {
                scoreRank.push({index: eIndex, point: point});
            } else {
                noScoreRank.push(eIndex);
            }
        });

        // 获取比较的数组
        var qZhuangArray = [];

        if (scoreRank.length < 1) {
            qZhuangArray = noScoreRank;
        }else if (scoreRank.length == 1) {
            qZhuangArray.push (scoreRank[0].index);
        }else {
            // 进行排序
            scoreRank.sort (function (a, b) {
                return b.point - a.point;
            });

            for (var index = 0; index < scoreRank.length - 1; ++index) {
                qZhuangArray.push (scoreRank[index].index);
                if (scoreRank[index].point != scoreRank[index + 1].point) {
                    break;
                }
            }
        }

        console.log ("获取抢庄数列");

        var randIndex =  Ext.randArray(qZhuangArray);
        console.log ("获取抢庄的队列：" + randIndex);
        this._dealerIndex = randIndex;
        var length = qZhuangArray.length;

        this.broadcast("onDealerChanged", {
            dealer: this._dealerIndex,
            length: length,
            arrays: qZhuangArray
        });
        this._waitAddAnte();
    },

    _waitAddAnte: function(){
        this._roundStatus = RoundStatus.ADDANTE;
        this._waitAddAnteTime = Date.getStamp();
        this._roundDateStamp = new Date().getTime();

        this.broadcast("onStartAddAnte", {
            waitAddAnteTime: this.getHideOption("addAnteWaitMS"),
            dateStamp: this._roundDateStamp
        });

        // 需要对每个玩家发送该玩家对应的推注
        this._sendAllTuiZu ();

        if(this._waitTimer){
            clearTimeout(this._waitTimer);
        }

        this._waitTimer = setTimeout(function() {
            if (!this.isPlaying()) {
                return;
            }
            if (this._roundStatus != RoundStatus.ADDANTE) {
                return;
            }
            console.log("addAnteWaitMS = %d", this.getHideOption("addAnteWaitMS"));
            this.enumPlaying(function(eIndex, ePlayer) {
                if (ePlayer.getAnte() == 0 && eIndex != this._dealerIndex){
                    // 获取对应的场次的基础下注
                    var baseAdd = Const.addRule[this.getOption("baseRule")];
                    ePlayer.setAnte(baseAdd[0]);
                    this.broadcast("onPlayerAddAnte", {
                        playerIndex: ePlayer.getIndex(),
                        num: baseAdd[0]
                    });
                }
            }.bind(this));
            this.broadcast("onAddAnteFinish", {});
            this._waitPlayCards();
        }.bind(this), this.getHideOption("addAnteWaitMS"));
    },

    /**
     * 用于加注结束之后给玩家多摸一张牌
     * @private
     */
    _waitPlayCards: function() {

        if (this.getOption ("qZhuangMode") != Const.qZhuangMode.MPQZ) {
            this.initPlayersHandCards();
        }

        this._roundDateStamp = new Date().getTime();

        this.broadcast("onStartPlayCards", {
            playWaitTime: this.getHideOption("playWaitMS"),
            dateStamp: this._roundDateStamp
        });
        this._roundStatus = RoundStatus.PLAY;

        // 如果提前到下一步骤的话，那就先清空
        if(this._waitTimer){
            clearTimeout(this._waitTimer);
        }

        this._waitTimer = setTimeout(function() {
            if (this._roundStatus != RoundStatus.PLAY) {
                return;
            }
            this.enumPlaying(function(eIndex, ePlayer){
                if(ePlayer._playCards == false){
                    ePlayer.checkPattern();

                    var resp = {
                        playerIndex: ePlayer.getIndex(),
                        handCards: ePlayer.getHandCards().getInitCards(),
                        selectedCards: ePlayer.getSelectedCards(),
                        niu: ePlayer.getRoundPattern(),
                        niuScore: ePlayer.getRoundPatternScore()
                    };
                    this.broadcast("onPlayCards", resp);
                }
            }.bind(this));
            this.broadcast("onPlayCardsFinish", {});
            this.settlementCurRound();
        }.bind(this), this.getHideOption("playWaitMS"));
    },

    _changeCurPlay: function(index){
        if(this._getPlayingPlayerCount() == 1 || this._roundTurn >= 10){
            this.settlementCurRound();
        }else{
            if(index){
                this._curPlay = index;
            }else{
                this._curPlay = this._getNextPlayer(this._curPlay);
            }
            this._sendCurPlay();
        }
    },

    _getPlayingPlayerCount: function () {
        var count = 0;
        this.enumPlaying(function (eIndex, ePlayer) {
            if(ePlayer._giveUp){
                return;
            }
            count += 1;
        });
        return count;
    },

    _getNextPlayer: function (fromIndex) {
        if (fromIndex < 1 || fromIndex > this.getMaxPlayer()) {
            fromIndex = 1;
        }
        var tmpIndex = fromIndex;
        do {
            tmpIndex = this.getNextIndex(tmpIndex);
            if(tmpIndex == 1){
                this._roundTurn += 1;
            }
            var tmpPlayer = this.getPlayerByIndex(tmpIndex);
            if (tmpPlayer && tmpPlayer.isPlaying() && tmpPlayer._giveUp == false) {
                break;
            }
        } while (tmpIndex != fromIndex);

        return tmpIndex;
    },

    _sendCurPlay: function() {
        var msg = {
            'curPlay': this._curPlay
        };
        this.broadcastReplay("onCurPlay", msg);
    },

    getAddScore: function (failer, winner) {

        var addRate = 1;

        // 抢庄倍数
        if (this.getOption("qZhuangMode") == Const.qZhuangMode.MPQZ
            || this.getOption("qZhuangMode") == Const.qZhuangMode.ZYQZ) {
            var dealerPlayer = this.getDealerPlayer();
            // 由于是抢庄模式，默认与庄家进行比较
            var robDeal = dealerPlayer.getRobDealer();
            if (robDeal > 0) {
                addRate *= robDeal;
            }
        }
        
        if (this.getOption("qZhuangMode") == Const.qZhuangMode.TBNN) {
            addRate *= winner.getAnte();
        }else {
            if (winner.getIndex() != this.getDealerIndex()) {
                addRate *= winner.getAnte();
            }else {
                addRate *= failer.getAnte();
            }
        }

        // 获取赢家底分倍数
        var baseScore = clone(winner.getRoundPatternScore());
        addRate = addRate * baseScore;

        if (this.getOption("playerTuiZhu")) {
            var patternScore = this._getTuiPatternScore(failer.getRoundPattern());
            failer.setLastPatternScore (patternScore);
            winner.setLastPatternScore (null);
        }

        winner.addRoundScore(addRate);
        failer.addRoundScore(-addRate);

        winner.addCompareResult(failer.getIndex());
        failer.addCompareResult(winner.getIndex());
    },

    getPatternScore: function (pattern) {
        if (this.getOption ("fanRule")
            && pattern >= Const.SpecRule["bottom"]
            && pattern <= Const.SpecRule["top"]) {
            return Const.SpecRule[pattern];
        }else {
            return Const.PatternScore[pattern];
        }
    },

    /**
     * 两个玩家相互比较
     * @param ePlayer
     * @param dealerPlayer
     */
    compareEach: function (ePlayer, dealerPlayer) {

        // 获取当前的抢庄模式
        var result = ePlayer.compareEach(dealerPlayer);
        var winPlayer;
        var failPlayer;

        if (result) {
            winPlayer = ePlayer;
            failPlayer = dealerPlayer;
        }else {
            winPlayer = dealerPlayer;
            failPlayer = ePlayer;
        }

        this.getAddScore(failPlayer, winPlayer);
    },

    /**
     * 根据玩家牌型获取推注的值
     * @param pattern
     * @returns {*}
     * @private
     */
    _getTuiPatternScore: function (pattern) {

        // 获取对应的规则
        var tuiRule = Const.TuiRule[this.getOption("baseRule")];
        return tuiRule[pattern];
    },

    _sendAllTuiZu: function () {

        // 获取房间规则
        var isHaveTuiZu = this.getOption("playerTuiZhu");

        this.enumPlaying( function (eIndex, ePlayer) {

            if (ePlayer && eIndex != this.getDealerIndex()) {

                var addResult = [];
                if (this.getOption ("qZhuangMode") != Const.qZhuangMode.TBNN) {
                    addResult = clone (Const.addRule[this.getOption("baseRule")]);

                    var tuiZu = ePlayer.getLastPatternScore();
                    if (isHaveTuiZu && tuiZu) {
                        addResult.push (tuiZu);
                    }

                    ePlayer.setTuiZuResult (addResult);

                    // 发送所有玩家的推注
                    ePlayer.send ("onPlayerTuiZu", {
                        tuiZu : addResult
                    })
                }else {
                    var curResult = clone (Const.addRule[this.getOption("baseRule")]);

                    ePlayer.setAnte (curResult[0]);
                }
            }
        }.bind (this));
    }
});